#ifndef WIN32
#include <arpa/inet.h>
#else
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#endif
#include <sstream>
#include "msg_base.h"

namespace herm{

MsgException::MsgException(const std::string& file, int line, const std::string& func, int type, const std::string& desc)
	: Exception(file, line, func, type, 0, desc)
{
}

Encoder::Encoder(char* buf, int len)
{
	m_buf = buf;
	m_len = len;
	m_pos = 0;
}

Encoder& Encoder::operator<<(uint8_t val)
{
	EncodeBuf(&val, sizeof(uint8_t));

	return *this;
}

Encoder& Encoder::operator<<(uint16_t val)
{
	uint16_t tmp = htons(val);
	EncodeBuf(&tmp, sizeof(uint16_t));

	return *this;
}

Encoder& Encoder::operator<<(uint32_t val)
{
	uint32_t tmp = htonl(val);
	EncodeBuf(&tmp, sizeof(uint32_t));

	return *this;
}

Encoder& Encoder::operator<<(float val)
{
	EncodeBuf(&val, sizeof(float));

	return *this;
}

Encoder& Encoder::operator<<(double val)
{
	EncodeBuf(&val, sizeof(double));

	return *this;
}

Encoder& Encoder::operator<<(const std::string& str)
{
	EncodeBuf(str.c_str(), (int)str.size());

	return *this;
}

Encoder& Encoder::operator<<(const Data& data)
{
	EncodeBuf(data.data, data.len);

	return *this;
}

Encoder& Encoder::operator<<(Fun f)
{
	return (*f)(*this);
}

void Encoder::EncodeSize(int sizeType, int sizeVal)
{
	if (sizeType != 0)
	{
		if (sizeType == 1)
		{
			uint8_t size = (uint8_t)sizeVal;
			*this << size;
		}
		else if (sizeType == 2)
		{
			uint16_t size = (uint16_t)sizeVal;
			*this << size;
		}
		else if (sizeType == 4)
		{
			uint32_t size = (uint32_t)sizeVal;
			*this << size;
		}
		else
			throw HERM_MSG_EXCEPTION(ST_ENCODE_FAILED, "Encode body size error!");
	}
}

Encoder& endl(Encoder& encoder)
{
	uint16_t length = htons((uint16_t)encoder.Length());
	encoder.EncodeBuf(0, &length, 2);

	return encoder;
}

Decoder::Decoder(const char* buf, int len)
{
	m_buf = buf;
	m_len = len;
	m_pos = 0;
}

const Decoder& Decoder::operator>>(uint8_t& val) const
{
	DecodeBuf(&val, sizeof(uint8_t));
	const_cast<Decoder*>(this)->m_curSegSize = val;

	return *this;
}

const Decoder& Decoder::operator>>(uint16_t& val) const
{
	uint16_t tmp;
	DecodeBuf(&tmp, sizeof(uint16_t));
	val = ntohs(tmp);
	const_cast<Decoder*>(this)->m_curSegSize = val;

	return *this;
}

const Decoder& Decoder::operator>>(uint32_t& val) const
{
	uint32_t tmp;
	DecodeBuf(&tmp, sizeof(uint32_t));
	val = ntohl(tmp);
	const_cast<Decoder*>(this)->m_curSegSize = val;

	return *this;
}

const Decoder& Decoder::operator>>(std::string& s) const
{
	if (m_len - m_pos < m_curSegSize)
		throw HERM_MSG_EXCEPTION(ST_DECODE_FAILED, "Decode buffer is end!");
	
	s.assign(m_buf + m_pos, m_curSegSize);
	const_cast<Decoder*>(this)->m_pos += m_curSegSize;

	return *this;
}

const Decoder& Decoder::operator>>(Data& data) const
{
	if (m_len - m_pos < m_curSegSize)
		throw HERM_MSG_EXCEPTION(ST_DECODE_FAILED, "Decode buffer is end!");

//	if (data.len > m_curSegSize)
//		throw HERM_MSG_EXCEPTION(ST_DECODE_FAILED, "Data buffer is too short!");

	Decoder* d = const_cast<Decoder*>(this); 
	data.data = (char*)d->m_buf + d->m_pos;
	data.len = m_curSegSize;
	const_cast<Decoder*>(this)->m_pos += m_curSegSize;

	return *this;
}

void Decoder::DecodeSize(int sizeType) const
{
	if (sizeType != 0)
	{
		if (sizeType == 1)
		{
			uint8_t size;
			*this >> size;
		}
		else if (sizeType == 2)
		{
			uint16_t size;
			*this >> size;
		}
		else if (sizeType == 4)
		{
			uint32_t size;
			*this >> size;
		}
		else
			throw HERM_MSG_EXCEPTION(ST_DECODE_FAILED, "Encode body size error!");
	}
}
}
